<html>
<head><meta charset="utf-8"><title>Why Compile impl FnMut for &quot;Non mutable&quot; closure? · t-compiler/help · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/index.html">t-compiler/help</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Why.20Compile.20impl.20FnMut.20for.20.22Non.20mutable.22.20closure.3F.html">Why Compile impl FnMut for &quot;Non mutable&quot; closure?</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="186957515"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Why%20Compile%20impl%20FnMut%20for%20%22Non%20mutable%22%20closure%3F/near/186957515" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Derek <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Why.20Compile.20impl.20FnMut.20for.20.22Non.20mutable.22.20closure.3F.html#186957515">(Jan 30 2020 at 06:02)</a>:</h4>
<p>In following example, because s1 is not mutable, So closure can't mutate it's captured variable s1.  how ever, trait bound <code>where F: FnMut()</code> satisfied. No error triggered.  But obviously closure can't really mutate anything. why compiler have to impl FnMut in this case. <br>
I also checked source code of libcore/ops/function.rs. the relationship of FnOnce, FnMut and Fn are:</p>
<div class="codehilite"><pre><span></span><span class="k">pub</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="nb">Fn</span><span class="o">&lt;</span><span class="n">Args</span><span class="o">&gt;</span>: <span class="nb">FnMut</span><span class="o">&lt;</span><span class="n">Args</span><span class="o">&gt;</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="nb">FnMut</span><span class="o">&lt;</span><span class="n">Args</span><span class="o">&gt;</span>: <span class="nb">FnOnce</span><span class="o">&lt;</span><span class="n">Args</span><span class="o">&gt;</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="nb">FnOnce</span><span class="o">&lt;</span><span class="n">Args</span><span class="o">&gt;</span><span class="w"></span>
</pre></div>


<p>In another word, FnOnce is a supertrait of  FnMut, and FnMut is a supertrait of Fn. So in order to implement Fn, we have to implement FnMut. <br>
But seems it doesn't make sense. if I try to s1.push_str(" Rust"); compiler will throw an error,  that basically means compiler is smart enough to know if the closure will make any change. if not, why have to implement FnMut.  why can't make Fn is supertrait of FnMut. <br>
I must missed something, but couldn't dig out, hope I can get some help here. Thanks! </p>
<div class="codehilite"><pre><span></span><span class="k">fn</span> <span class="nf">call</span><span class="o">&lt;</span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="k">mut</span><span class="w"> </span><span class="n">func</span>: <span class="nc">F</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="k">where</span><span class="w"> </span><span class="n">F</span>: <span class="nb">FnMut</span><span class="p">()</span><span class="w">  </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">func</span><span class="p">();</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">s1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;Hello&quot;</span><span class="p">.</span><span class="n">to_string</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">closure</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="c1">// This will trigger &quot;cannot borrow as mutable&quot;</span>
<span class="w">        </span><span class="c1">// s1.push_str(&quot; Rust&quot;);</span>
<span class="w">        </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;{} Rust&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">s1</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="p">};</span><span class="w"></span>
<span class="w">    </span><span class="n">call</span><span class="p">(</span><span class="n">closure</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>



<a name="186978730"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Why%20Compile%20impl%20FnMut%20for%20%22Non%20mutable%22%20closure%3F/near/186978730" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Areredify <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Why.20Compile.20impl.20FnMut.20for.20.22Non.20mutable.22.20closure.3F.html#186978730">(Jan 30 2020 at 12:07)</a>:</h4>
<p>FnMut does not mean that the closure mutates state, it means that it <em>might</em> mutate state. That, in turn, means that you have to have a mutable receiver in order to call an FnMut. Fn trait means that the it does not mutate state, so if we make Fn a supertrait of FnMut, it would mean that in order to mutate state, it would also need to not mutate state, which does not make sense.</p>



<a name="186999236"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Why%20Compile%20impl%20FnMut%20for%20%22Non%20mutable%22%20closure%3F/near/186999236" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Derek <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Why.20Compile.20impl.20FnMut.20for.20.22Non.20mutable.22.20closure.3F.html#186999236">(Jan 30 2020 at 15:46)</a>:</h4>
<p><span class="user-mention" data-user-id="251766">@Areredify</span> Thanks for you reply,  I really appreciate. If that's the only reason, In my option, <br>
"so if we make Fn a supertrait of FnMut, it would mean that in order to mutate state, it would also need to not mutate state, which does not make sense."<br>
This can be interpreted this way,  Fn is read only.  FnMut goes futher, it can mutate. as mutate will need read first. this kind like any permission management, readonly &lt; read/write. So following rule  would be more clear:</p>
<ol>
<li>with move key word, compiler implement FnOnce by default.</li>
<li>without mutate ability. compiler go further implement FnOnce and Fn.</li>
<li>with mutate ability, compiler go further implement FnMut. <br>
thanks</li>
</ol>



<a name="187081995"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Why%20Compile%20impl%20FnMut%20for%20%22Non%20mutable%22%20closure%3F/near/187081995" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Why.20Compile.20impl.20FnMut.20for.20.22Non.20mutable.22.20closure.3F.html#187081995">(Jan 31 2020 at 13:15)</a>:</h4>
<p><a href="https://doc.rust-lang.org/nightly/reference/types/closure.html#call-traits-and-coercions" target="_blank" title="https://doc.rust-lang.org/nightly/reference/types/closure.html#call-traits-and-coercions">https://doc.rust-lang.org/nightly/reference/types/closure.html#call-traits-and-coercions</a></p>



<a name="187082083"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Why%20Compile%20impl%20FnMut%20for%20%22Non%20mutable%22%20closure%3F/near/187082083" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Why.20Compile.20impl.20FnMut.20for.20.22Non.20mutable.22.20closure.3F.html#187082083">(Jan 31 2020 at 13:16)</a>:</h4>
<p><code>move</code> is about disabling smart inference, it has nothing to do with call traits.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>